{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "97909541",
   "metadata": {},
   "outputs": [],
   "source": [
    "import requests\n",
    "import os\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import keras\n",
    "from keras import layers\n",
    "from keras import models\n",
    "os.environ[\"CUDA_VISIBLE_DEVICES\"]=\"0\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2a2bb436",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 训练epochs数量\n",
    "EPOCHS = 20\n",
    "# 训练批大小\n",
    "BATCH_SIZE = 5\n",
    "# 输入的连续时间序列长度\n",
    "MAX_STEPS = 30\n",
    "# 前区号码种类数\n",
    "FRONT_VOCAB_SIZE = 10\n",
    "# 后区号码种类数\n",
    "# BACK_VOCAB_SIZE = 11\n",
    "# dropout随机失活比例\n",
    "DROPOUT_RATE = 0.5\n",
    "# 长短期记忆网络单元数\n",
    "LSTM_UNITS = 64\n",
    "# 前区需要选择的号码数量\n",
    "FRONT_SIZE = 5\n",
    "# 后区需要选择的号码数量\n",
    "# BACK_SIZE = 2\n",
    "# 保存训练好的参数的路径\n",
    "CHECKPOINTS_PATH = 'checkpoints2'\n",
    "# 预测下期号码时使用的训练好的模型参数的路径，默认使用完整数据集训练出的模型\n",
    "PREDICT_MODEL_PATH = '{}/model_checkpoint_x'.format(CHECKPOINTS_PATH)\n",
    "# 预测的时候，预测几注彩票,默认5注\n",
    "PREDICT_NUM = 5\n",
    "# 数据集路径\n",
    "DATASET_PATH = 'lotto.csv'\n",
    "# 数据集下载地址\n",
    "# LOTTO_DOWNLOAD_URL = 'https://www.js-lottery.com/PlayZone/downLottoData.html'\n",
    "LOTTO_DOWNLOAD_URL = 'http://106.13.233.100:3002/getLimitData/3000'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8e588cf2",
   "metadata": {},
   "outputs": [],
   "source": [
    "load_data = []\n",
    "def getData():\n",
    "  try:\n",
    "    resp = requests.get(LOTTO_DOWNLOAD_URL)\n",
    "    if resp.status_code == 200:\n",
    "        respJson = resp.json()\n",
    "        respJson.reverse()\n",
    "        for i in range(len(respJson)):\n",
    "          d = respJson[i]\n",
    "          # load_data.append([d[\"issueNo\"],d[\"one\"],d[\"two\"],d[\"three\"],d[\"four\"],d[\"five\"]])\n",
    "          # load_data.append([d[\"one\"],d[\"two\"],d[\"three\"],d[\"four\"],d[\"five\"]])\n",
    "          load_data.append(d[\"five\"])\n",
    "        # print(len(load_data))\n",
    "        # print(load_data)\n",
    "        # print(load_data[:10])\n",
    "        return load_data\n",
    "    else:\n",
    "      raise Exception('获取数据失败！')\n",
    "  except Exception as e:\n",
    "    print(e)\n",
    "\n",
    "# getData()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1731051e",
   "metadata": {},
   "outputs": [],
   "source": [
    "def split_data():\n",
    "  x=[]\n",
    "  y=[]\n",
    "  total = len(load_data)\n",
    "\n",
    "  if MAX_STEPS >= total: print(\"错误\")\n",
    "  for item in range(MAX_STEPS, total, 1):\n",
    "    x.append(load_data[item - MAX_STEPS:item])\n",
    "    y.append(load_data[item])\n",
    "  # print(y)\n",
    "  # print(x)\n",
    "\n",
    "  np_x = np.zeros((total-MAX_STEPS, MAX_STEPS,FRONT_VOCAB_SIZE))\n",
    "  np_y = np.zeros((total-MAX_STEPS,FRONT_VOCAB_SIZE))\n",
    "\n",
    "  for i in range(0, len(x), 1):\n",
    "    # print(i)\n",
    "    yy = y[i]\n",
    "    np_y[i][yy] = 1\n",
    "    for j in range(0, len(x[i]), 1):\n",
    "      xx = x[i][j]\n",
    "      np_x[i][j][xx] = 1\n",
    "      # print(j)\n",
    "\n",
    "  # print(np_x)\n",
    "  # print(np_y)\n",
    "\n",
    "  # 0.8训练。0.2测试。0.1预测测试\n",
    "  train_data_rate = 0.7\n",
    "  train_7 = int(train_data_rate * len(x))\n",
    "  test_1 = int(0.2 * len(x))\n",
    "\n",
    "  train_x = np_x[:train_7]\n",
    "  train_y = np_y[:train_7]\n",
    "  test_x = np_x[train_7:train_7+test_1]\n",
    "  test_y = np_y[train_7:train_7+test_1]\n",
    "  predict_x = np_x[train_7+test_1:]\n",
    "  predict_y = y[train_7+test_1:]\n",
    "  # print(9)\n",
    "  return train_x, train_y, test_x, test_y, predict_x, predict_y\n",
    "\n",
    "# train_x, train_y, test_x, test_y, predict_x, predict_y = split_data()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bef245cb",
   "metadata": {},
   "outputs": [],
   "source": [
    "def myModel():\n",
    "  # 这是一个多输入模型，inputs用来保存所有的输入层\n",
    "  inputs = []\n",
    "  # 这是一个多输出模型，outputs用来保存所有的输出层\n",
    "  outputs = []\n",
    "\n",
    "  # 输入层\n",
    "  x_input = layers.Input((MAX_STEPS, FRONT_VOCAB_SIZE))\n",
    "  # 双向循环神经网络\n",
    "  x = layers.Bidirectional(layers.LSTM(LSTM_UNITS, return_sequences=True))(x_input)\n",
    "  # 随机失活\n",
    "  x = layers.Dropout(rate=DROPOUT_RATE)(x)\n",
    "  # x = layers.Bidirectional(layers.LSTM(LSTM_UNITS, return_sequences=True))(x)\n",
    "  x = layers.TimeDistributed(layers.Dense(FRONT_VOCAB_SIZE * 3))(x)\n",
    "  x = layers.Dropout(rate=DROPOUT_RATE)(x)\n",
    "  # 平铺\n",
    "  x = layers.Flatten()(x)\n",
    "  # 全连接\n",
    "  x = layers.Dense(FRONT_VOCAB_SIZE, activation='relu')(x)\n",
    "  # 保存输入层\n",
    "  inputs.append(x_input)\n",
    "  # x = layers.Dense(FRONT_VOCAB_SIZE, activation='relu')(x)\n",
    "  outputs.append(x)\n",
    "\n",
    "  # 创建模型\n",
    "  model = models.Model(inputs, outputs)\n",
    "  # 指定优化器和损失函数\n",
    "  model.compile(optimizer=keras.optimizers.Adam(), metrics = ['accuracy'],\n",
    "    loss=[keras.losses.categorical_crossentropy for __ in range(FRONT_SIZE)],\n",
    "    loss_weights=[1, 1, 1, 1, 1])\n",
    "  # 查看网络结构\n",
    "  model.summary()\n",
    "\n",
    "  return model\n",
    "\n",
    "# model = myModel()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8d2836d9",
   "metadata": {},
   "outputs": [],
   "source": [
    "def train_cpu():\n",
    "  # 创建保存权重的文件夹\n",
    "  if not os.path.exists(CHECKPOINTS_PATH):\n",
    "    os.mkdir(CHECKPOINTS_PATH)\n",
    "\n",
    "  # 开始训练\n",
    "  epoch = EPOCHS\n",
    "  H = model.fit(train_x, train_y, validation_data=(test_x, test_y), batch_size=BATCH_SIZE, epochs=epoch)\n",
    "  # 保存当前权重\n",
    "  model.save_weights('{}/model_checkpoint_{}_{}_{}_{}_{}'.format(CHECKPOINTS_PATH, epoch, BATCH_SIZE, MAX_STEPS,DROPOUT_RATE,LSTM_UNITS))\n",
    "  # print('已训练完第{}轮，尝试模拟购买彩票...'.format(epoch))\n",
    "  # results.append(simulate(lotto_dataset.test_np_x, lotto_dataset.test_np_y))\n",
    "\n",
    "  x = np.arange(0, epoch)\n",
    "  plt.plot(x, H.history[\"loss\"], label=\"loss\")\n",
    "  plt.plot(x, H.history[\"val_loss\"], label=\"val_loss\")\n",
    "  plt.plot(x, H.history[\"accuracy\"], label=\"accuracy\")\n",
    "  plt.plot(x, H.history[\"val_accuracy\"], label=\"val_accuracy\")\n",
    "  plt.title('epoch:{}, BATCH_SIZE:{}, MAX_STEPS:{}, DROPOUT_RATE:{}, LSTM_UNITS:{}'.format(epoch,BATCH_SIZE,MAX_STEPS,DROPOUT_RATE,LSTM_UNITS))\n",
    "  plt.legend()\n",
    "  plt.show()\n",
    "  plt.savefig('epoch={}-BATCH_SIZE={}-MAX_STEPS={}-DROPOUT_RATE={}-LSTM_UNITS={}.png'.format(epoch,BATCH_SIZE,MAX_STEPS,DROPOUT_RATE,LSTM_UNITS))\n",
    "\n",
    "# train_cpu()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "30f5b53f",
   "metadata": {},
   "source": [
    "## 下面开始训练"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "155b2d23",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 训练epochs数量\n",
    "EPOCHS = 20\n",
    "# 训练批大小\n",
    "BATCH_SIZE = 2\n",
    "# 输入的连续时间序列长度\n",
    "MAX_STEPS = 20\n",
    "# 前区号码种类数\n",
    "FRONT_VOCAB_SIZE = 10\n",
    "# dropout随机失活比例\n",
    "DROPOUT_RATE = 0.3\n",
    "# 长短期记忆网络单元数\n",
    "LSTM_UNITS = 64\n",
    "# 前区需要选择的号码数量\n",
    "FRONT_SIZE = 5\n",
    "# 保存训练好的参数的路径\n",
    "CHECKPOINTS_PATH = 'checkpoints2'\n",
    "# 预测下期号码时使用的训练好的模型参数的路径，默认使用完整数据集训练出的模型\n",
    "PREDICT_MODEL_PATH = '{}/model_checkpoint_x'.format(CHECKPOINTS_PATH)\n",
    "# 预测的时候，预测几注彩票,默认5注\n",
    "PREDICT_NUM = 5\n",
    "# 数据集路径\n",
    "DATASET_PATH = 'lotto.csv'\n",
    "# 数据集下载地址\n",
    "LOTTO_DOWNLOAD_URL = 'http://106.13.233.100:3002/getLimitData/3000'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2358658d",
   "metadata": {},
   "outputs": [],
   "source": [
    "load_data = getData()\n",
    "train_x, train_y, test_x, test_y, predict_x, predict_y = split_data()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f8e46a8f",
   "metadata": {},
   "outputs": [],
   "source": [
    "model = myModel()\n",
    "train_cpu()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "60a037f1",
   "metadata": {},
   "source": [
    "## 下面预测与验证"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7e0d7764",
   "metadata": {},
   "outputs": [],
   "source": [
    "def sample(preds, temperature=1.0):\n",
    "  \"\"\"\n",
    "  从给定的preds中随机选择5个下标。\n",
    "  当temperature固定时，preds中的值越大，选择其下标的概率就越大；\n",
    "  当temperature不固定时，\n",
    "      temperature越大，选择值小的下标的概率相对提高，\n",
    "      temperature越小，选择值大的下标的概率相对提高。\n",
    "  :param preds: 概率分布序列，其和为1.0\n",
    "  :param temperature: 当temperature==1.0时，相当于直接对preds进行轮盘赌法\n",
    "  :return:\n",
    "  \"\"\"\n",
    "  preds = np.asarray(preds).astype(np.float64)\n",
    "  # preds1 = np.log(preds) / temperature\n",
    "  exp_preds = np.exp(preds)\n",
    "  preds2 = exp_preds / np.sum(exp_preds)\n",
    "  # probas = np.random.multinomial(1, preds2, 1)\n",
    "  # re = np.argmax(probas)\n",
    "  responseTo = []\n",
    "  while True:\n",
    "    # probas = np.random.multinomial(1, preds2, 1)\n",
    "    # re = np.argmax(probas)\n",
    "    re = np.argmax(preds2)\n",
    "    if re in responseTo:\n",
    "      continue\n",
    "    else:\n",
    "      responseTo.append(re)\n",
    "      preds2[re] = 0.0\n",
    "    if len(responseTo) >= 5:\n",
    "      break\n",
    "  return responseTo\n",
    "\n",
    "def myPredict():\n",
    "  # 加载模型参数\n",
    "  # model.load_weights(PREDICT_MODEL_PATH)\n",
    "  model.load_weights(\"checkpoints2/model_checkpoint_10_4_20_0.3_32\")\n",
    "  # 开始预测\n",
    "  predicts = model.predict(predict_x, batch_size=1)\n",
    "  correct = 0\n",
    "  total =  len(predicts)\n",
    "  for i in range(total):\n",
    "    # print(\"当前为：{}\".format(i))\n",
    "    # if i == 250:\n",
    "    #   print(\"\")\n",
    "    balls= sample(predicts[i])\n",
    "    if predict_y[i] in balls:\n",
    "      correct = correct + 1\n",
    "  print(\"正确的个数为：{}\".format(correct))\n",
    "  print(\"正确的百分比为：{}\".format(correct/total))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "040f0a21",
   "metadata": {},
   "outputs": [],
   "source": [
    "# myPredict()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bf28e362",
   "metadata": {},
   "outputs": [],
   "source": [
    "EPOCHS_=[20,60]\n",
    "BATCH_SIZE_=[2, 4, 8, 16, 32, 64]\n",
    "MAX_STEPS_=[2, 4, 8, 16, 32, 64]\n",
    "DROPOUT_RATE_=[0.3, 0.6]\n",
    "LSTM_UNITS_=[8, 16, 32, 64]\n",
    "list = []\n",
    "\n",
    "for e in EPOCHS_:\n",
    "  # print(e)\n",
    "  for b in BATCH_SIZE_:\n",
    "    # print(b)\n",
    "    for m in MAX_STEPS_:\n",
    "      # print(m)\n",
    "      for d in DROPOUT_RATE_:\n",
    "        # print(d)\n",
    "        for l in LSTM_UNITS_:\n",
    "          # print(l)\n",
    "          list.append([e, b, m, d, l])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dd0cc8ce",
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "x = np.arange(0, 2)\n",
    "plt.plot(x, [3, 2], label=\"loss\")\n",
    "plt.plot(x, [5, 7], label=\"val_loss\")\n",
    "plt.title('epoch:9, BATCH_SweIZE:, MAX_STEPSwe:,twt DROPOqrUT_RAwerTE:, LSTwetwM_UNITS:wegsd:24')\n",
    "plt.legend()\n",
    "plt.savefig('test.jpg', bbox_inches = 'tight')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "daabfdc9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['a00002', '', '20', '2', '2', '0.3', '32']"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\"a00002__20_2_2_0.3_32\".split(\"_\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'correct': 100, 'total': 200, 'bfb': '30', 'file': 'a00316__60_2_16_0.6_8', 'EPOCHS': 20, 'BATCH_SIZE': 20, 'MAX_STEPS': 20, 'DROPOUT_RATE': 20, 'LSTM_UNITS': 20}\n",
      "30\n",
      "<class 'list'>\n"
     ]
    }
   ],
   "source": [
    "import json\n",
    "with open(\"./predictData.json\",'r') as load_f:\n",
    "  load_dict = json.load(load_f)\n",
    "print(load_dict[0])\n",
    "print(load_dict[0][\"bfb\"])\n",
    "print(type(load_dict))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "57a005a6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'one': 1, 'two': {'j': ['a']}}\n",
      "<class 'dict'>\n"
     ]
    }
   ],
   "source": [
    "import json\n",
    "test_dict = '{\"one\":1, \"two\":{\"j\":[\"a\"]}}'\n",
    "# js = json.dumps(test_dict)\n",
    "new_dict = json.loads(test_dict)\n",
    "print(new_dict)\n",
    "print(type(new_dict))\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.9.13 64-bit",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.13"
  },
  "vscode": {
   "interpreter": {
    "hash": "239cd0f6924d34dc9a29cd51ff042db2679e9319f05891fd61214d5969f7bbf8"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
